EC2のユーザデータでnvmとNode.jsをインストールしようとしたら苦労したこと

EC2のユーザデータでnvmとNode.jsをインストールしようとしたら苦労したこと

Clock Icon2024.08.22

こんにちは、ゲームソリューション部のsoraです。
今回は、EC2のユーザデータでnvmとNode.jsをインストールしようとしたら苦労したことについて書いていきます。
今回使用するAMIはAmazon Linux2023です。

上手くいったユーザデータ

まず先に上手くいったユーザデータは以下です。

#!/bin/bash

# Update the package list and install necessary packages
dnf update -y

# nvmとnodejsのインストール(マルチパート形式)
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud-init directives

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
# nvmのインストール
if ! su - ec2-user -c "command -v nvm" > /dev/null 2>&1; then
  su - ec2-user -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash"
  su - ec2-user -c "source ~/.bashrc"
fi

# nodejsのインストール
if ! su - ec2-user -c "command -v node" > /dev/null 2>&1; then
  su - ec2-user -c "nvm install --lts"
fi
--//--

結論に至るまでに試したこと

ユーザデータを使わずにインストール

ユーザデータでのインストールをする前に、手動でインストールして上手くいくかを確認してみます。

sudo dnf update -y
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
source ~/.bashrc
nvm install --lts

実行後にインストールされているかの確認をしてみると、問題なくバージョンが確認できます。

nvm --version
0.40.0
node --version
v20.17.0

上手くいったコマンドをそのままユーザデータに記載

上手くいったコマンドをそのままユーザデータに記載して起動してみます。
ユーザデータのため、sudoは消しています。

dnf update -y
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
source ~/.bashrc
nvm install --lts

これは上手くいきませんでした。
理由としては、ユーザデータはrootで実行されるため、.nvmディレクトリがroot配下に作成され、ec2-userから呼び出せないためです。
パスを変更したりしたものの、結局上手くいかなかったです。(パスの設定が悪いかもですが)

ユーザデータでec2-userとして実行するように書き換える

先ほどはrootでnvmのインストールをして、.nvmディレクトリがroot配下に作成されたため、ec2-userとしてコマンドを実行するように書き換えてみます。
su -を書いていますがおそらく不要です)

dnf update -y
su - ec2-user -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash"
su - ec2-user -c "source ~/.bashrc"
su - ec2-user -c "nvm install --lts"

これだとうまくいかなかったため、ユーザデータ実行時のログを見てみます。

cat /var/log/cloud-init-output.log
# (以下抜粋)
init__.py[WARNING]: Unhandled non-multipart (text/x-not-multipart) userdata: 'b'su - ec2-user -c "curl -'...'

マルチパート形式で記述がされておらず、su - ec2-user -c …が上手く実行できていないみたいです。

マルチパート形式で書き換える

エラーに従ってマルチパート形式で書き換えます。
マルチパート形式で記載すると、インスタンス起動時に毎回実行されてしまうため、ifを入れてnvmとnodejsがインストールされていれば処理をスキップするようにしています。

#!/bin/bash

# Update the package list and install necessary packages
dnf update -y

# nvmとnodejsのインストール(マルチパート形式)
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud-init directives

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
# nvmのインストール
if ! su - ec2-user -c "command -v nvm" > /dev/null 2>&1; then
  su - ec2-user -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash"
  su - ec2-user -c "source ~/.bashrc"
fi

# nodejsのインストール
if ! su - ec2-user -c "command -v node" > /dev/null 2>&1; then
  su - ec2-user -c "nvm install --lts"
fi
--//--

起動したインスタンスにて以下コマンドを実行してみると、nvmとnodejsがインストールされていることが確認できました。

nvm --version
0.40.0
node --version
v20.17.0

最後に

今回は、EC2のユーザデータでnvmとNode.jsをインストールしようとしたら苦労したことを記事にしました。
どなたかの参考になると幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.